#include "FCFS_Scheduler.h"
#include "SJF_Scheduler.h"
#include "RR_Scheduler.h"
#include "SRTF_Scheduler.h"
#include "Process.h"
#include <iostream>
#include <vector>
#include <stdlib.h>
#include <time.h>
using namespace std;

vector<Process*> createProcesses(vector<Process*> &listOfProcesses, const int NUM_PROCESSES);


int main()
{
	vector<Process*> listOfProcesses;
	vector<Process> nextJob;
	const int NUM_PROCESSES = 50;
	FCFS_Scheduler firstCome_FirstServe;
	SJF_Scheduler shortestJobFirst;
	RR_Scheduler roundRobin(15), roundRobinTwo(30);
	SRTF_Scheduler srtf;

	createProcesses(listOfProcesses, NUM_PROCESSES);

	//cout << "size: " << listOfProcesses.size() << endl << endl;

	firstCome_FirstServe.init(listOfProcesses);
	shortestJobFirst.init(listOfProcesses);
	roundRobin.init(listOfProcesses);
	roundRobinTwo.init(listOfProcesses);
	srtf.init(listOfProcesses);

	/*firstCome_FirstServe.sortProcesses();
	firstCome_FirstServe.getNextProcess();
	firstCome_FirstServe.runScheduler();
	cout << "Unsorted....." << endl;
	firstCome_FirstServe.printList();
	firstCome_FirstServe.sortProcesses();
	cout << "\nSorted ..... " << endl;*/
	firstCome_FirstServe.runScheduler();
	firstCome_FirstServe.determineStats();
	//firstCome_FirstServe.printList();
	cout << "MWT for First-Come-First-Served: " << firstCome_FirstServe.getMeanWaitingTime() << endl;

	
	shortestJobFirst.runScheduler();
	shortestJobFirst.determineStats();
	//shortestJobFirst.printList();

	roundRobin.runScheduler();
	roundRobin.determineStats();
	

	cout << "MWT for Shortest Job First : " << shortestJobFirst.getMeanWaitingTime() << endl;

	cout << "Scheduler results using " << NUM_PROCESSES << endl;
	cout << "                        " << "    MWT   " << "   MTAT   " << "   MRT   \n";
	cout << "First Come First Serve  " << firstCome_FirstServe.getMeanWaitingTime() << "    " <<  firstCome_FirstServe.getMeanTurnAroundTime() << "    " << firstCome_FirstServe.getMeanResponseTime() << endl;
	cout << "Shortest Job First      " << shortestJobFirst.getMeanWaitingTime()     << "    " <<  shortestJobFirst.getMeanTurnAroundTime()     << "    " << shortestJobFirst.getMeanResponseTime()     << endl;
	cout << "Round Robin (15ms)      " << roundRobin.getMeanWaitingTime()           << "    " <<  roundRobin.getMeanTurnAroundTime()           << "    " << roundRobin.getMeanResponseTime()           << endl;
	cout << "Round Robin (30ms)      " << roundRobinTwo.getMeanWaitingTime()        << "    " <<  roundRobinTwo.getMeanTurnAroundTime()        << "    " << roundRobinTwo.getMeanResponseTime()        << endl;
	cout << endl;
	cout << endl;
	cout << "Legend:   Mean Waiting Time = MWT        Mean Turn Around Time = MTAT       Mean Reponse Time = MRT \n";

	//roundRobin.printList();

	//roundRobin.printList();

	//cout << "MWT for RoundRobin : " << roundRobin.getMeanWaitingTime() << endl;

	//srtf.runScheduler();



	listOfProcesses.~vector<Process*>();




	return 0;
}

/*
    @Description Creates a process for the CPU to execute
    @Return vector<Process*>
    @Author Stephen Durfey
 
*/
vector<Process*> createProcesses(vector<Process*> &listOfProcesses, const int NUM_PROCESSES)
{
	int randBurst = 0;
	int randStart = 0;
	int randID = 0;

	srand(time(NULL));

	for(int index = 0; index < NUM_PROCESSES; index++)
	{
		randBurst = (rand() % (200 - 10 + 1)) + 10;
		randStart = (rand() % (100 - 0 + 1));
		randID = 1 + rand() % 10000;
		listOfProcesses.push_back(new Process(randBurst, randStart, randID));
	}

	return listOfProcesses;
}